package com.sysu.ooad.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.sysu.ooad.dao.GroupDao;
import com.sysu.ooad.dao.HomeworkDao;
import com.sysu.ooad.dao.TaskDao;
import com.sysu.ooad.dto.GroupFacade;
import com.sysu.ooad.dto.HomeworkFacade;
import com.sysu.ooad.dto.StudentFacade;
import com.sysu.ooad.dto.TaskFacade;
import com.sysu.ooad.entity.Course;
import com.sysu.ooad.entity.Group;
import com.sysu.ooad.entity.Homework;
import com.sysu.ooad.entity.Student;
import com.sysu.ooad.entity.Task;
import com.sysu.ooad.service.TaskService;

@Component("taskService")
public class TaskServiceImpl implements TaskService {
	private TaskDao taskDao;
	private HomeworkDao homeworkDao;
	private GroupDao groupDao;
	
	
	public GroupDao getGroupDao() {
		return groupDao;
	}
	@Resource
	public void setGroupDao(GroupDao groupDao) {
		this.groupDao = groupDao;
	}
	public TaskDao getTaskDao() {
		return taskDao;
	}
	@Resource
	public void setTaskDao(TaskDao taskDao) {
		this.taskDao = taskDao;
	}

	public HomeworkDao getHomeworkDao() {
		return homeworkDao;
	}
	@Resource
	public void setHomeworkDao(HomeworkDao homeworkDao) {
		this.homeworkDao = homeworkDao;
	}
	public Task addTask(String title, String requirement, Date deadline,
			Course c) {
		Task task = new Task();
		task.setTitle(title);
		task.setCourse(c);
		task.setDeadline(deadline);
		task.setPublishTime(new Date());
		task.setRequirement(requirement);
		taskDao.add(task);
		return task;
	}
	
	public List<Task> findTasksByCourse(Course c) {
		return taskDao.findByCourse(c);
	}
	
	public Homework commitHomework(String fileName, Student student, Task task) {
		Homework homework = homeworkDao.findByTaskAndStudent(student, task);
		if(homework != null) {
			homework.setFilename(fileName);
			homework.setTime(new Date());
			homeworkDao.update(homework);
		}
		else {
			homework = new Homework();
			homework.setStudent(student);
			homework.setTask(task);
			homework.setTime(new Date());
			homework.setFilename(fileName);
			homeworkDao.add(homework);
		}
		return homework;
	}
	public List<Homework> findByGroup(Group g) {
		return homeworkDao.findByGroup(g);
	}
	public Map<Task, List<Homework> > findTaskHomeworkMapByGroup(Group g) {
		Map<Task, List<Homework> > map = new HashMap<Task, List<Homework> >();
		List<Homework> homeworks = homeworkDao.findByGroup(g);
		System.out.println(homeworks.size());
		for(Homework h : homeworks) {
			if(!map.containsKey(h.getTask())) {
				map.put(h.getTask(), new ArrayList<Homework>());
			}
			map.get(h.getTask()).add(h);
		}
		return map;
	}
	public Task findTaskByPosition(int pos, Course c) {
		return taskDao.findByPositionOrderByPublishTime(pos, c);
	}
	public List<Homework> findHomeworksByStudent(Student s) {
		return homeworkDao.findByStudent(s);
	}
	public List<Task> findNotCloseTasksByCourse(Course c) {
		return taskDao.findNotCloseTasksByCourse(c);
	}
	public List<Homework> findHomeworksByTaskAndGroup(Task task, Group g) {
		return homeworkDao.findByTaskAndGroup(task, g);
	}
	public Task findTaskById(Integer id) {
		return taskDao.findById(id);
	}
	public int countOfTasksByCourse(Course c) {
		return taskDao.countByCourse(c);
	}
	public void sortHomeworksOfOneTaskByLeader(Task task, Student leader,
			Integer[] sortResult) {
//		if(!leader.getGroup().getId().equals(leader.getId())) return;
		for (int i = 0; i < sortResult.length; i++) {
			Homework h = homeworkDao.findById(sortResult[i]);
			if(h != null && h.getTask().equals(task)) {
				h.setRank(i + 1);
				homeworkDao.update(h);
			}
		}
	}
	
	public List<GroupFacade> findGroupsFacadeWithHomeworks(Course c, Task task) {
		List<GroupFacade> groupsFacade = new ArrayList<GroupFacade>();
		List<Group> groups = groupDao.findByCourse(c);
		for(Group g: groups) {
			GroupFacade groupFacade = new GroupFacade(g);
			for(StudentFacade studentFacade : groupFacade.getStudents()) {
				Student s = new Student();
				s.setId(studentFacade.getId());
				Homework h = homeworkDao.findByTaskAndStudent(s, task);
				if(h != null) {
					studentFacade.setHomework(new HomeworkFacade(h));
				}
				else {
					h = new Homework();
					studentFacade.setHomework(new HomeworkFacade(new Homework()));
				}
			}
			groupsFacade.add(groupFacade);
		}
		
		return groupsFacade;
	}
	
	public void giveScoreToGroup(Task task, Group group, int maxScore, int minScore) {
		List<Homework> homeworks = homeworkDao.findByTaskAndGroup(task, group);
		Collections.sort(homeworks, new Comparator<Homework>(){
			public int compare(Homework h1, Homework h2) {
				if(h1.getRank() < h2.getRank()) return 1;
				else return -1;
			}
		});
		
		double interval = (double)(maxScore - minScore) / (homeworks.size() - 1);
		System.out.println(interval);
		double score = minScore;
		for(Homework h : homeworks) {
			h.setGrade((int)Math.floor(score + 0.5));
			homeworkDao.update(h);
			score += interval;
		}
	}
	public void updateTask(Task task) {
		Task t = taskDao.findById(task.getId());
		t.setTitle(task.getTitle());
		t.setRequirement(task.getRequirement());
		t.setDeadline(task.getDeadline());
		taskDao.update(t);
	}
	
	public List<TaskFacade> findTasksByStudentWithHomework(Student s) {
		List<Task> tasks = taskDao.findByCourse(s.getCourse());
		List<TaskFacade> taskFacades = new ArrayList<TaskFacade>();
		for(Task t : tasks) {
			Homework h = homeworkDao.findByTaskAndStudent(s, t);
			TaskFacade taskFacade = new TaskFacade(t);
			if(h != null)
				taskFacade.getHomeworks().add(new HomeworkFacade(h));
			taskFacades.add(taskFacade);
		}
		return taskFacades;
	}
}
